-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tilepyramids to PyramidScheme #49
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #49 +/- ##
==========================================
- Coverage 66.03% 57.88% -8.16%
==========================================
Files 3 6 +3
Lines 265 387 +122
==========================================
+ Hits 175 224 +49
- Misses 90 163 +73 ☔ View full report in Codecov by Sentry. |
We should also add some tests for this functionality. I took care of the compat entries already. |
src/tilepyramids.jl
Outdated
if mode === :band | ||
return MapTileDiskArray{rgbeltype(et),3,typeof(prov)}(prov, zoom, size(testtile, 1), nband) | ||
elseif mode === :rgb | ||
return MapTileDiskArray{et,2,typeof(prov)}(prov, zoom, size(testtile, 1), nband) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the number of bands be one in the case that the RGB info is in the color element type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well there are no bands in this case, since the resulting array is 2d, and the field should never be accessed
src/tilepyramids.jl
Outdated
y1, y2 = first(ex1.Y), last(ex2.Y) | ||
stepx = (x2 - x1) / npix | ||
stepy = (y2 - y1) / npix | ||
x = X(range(x1 + stepx / 2, x2 - stepx / 2, length=npix)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add here that these are intervals? Because most likely in the tiles the value of a pixel should represent the average over the whole pixel area and not a point measurement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this would indeed be better, I will look into it
The eachchunk result of a Pyramid from the Openstreetmap providers seems wrong for me. julia> size(eachchunk(pyr))
(1, 5, 134217728)
julia> eachchunk(pyr)[1,1,1]
(1:3, 1:33333333, 1:1) |
this can still get some tests for the chunking structure.
plotting of a pyramid from a provider does not work. using GLMakie, PyramidScheme, TileProviders
julia> prov = TileProviders.OpenStreetMap(); pyr = Pyramid(prov)
julia> plot(pyr, colorbar=false)
ERROR: MethodError: no method matching defaultlimits(::Tuple{String, String}, ::typeof(identity))
Closest candidates are:
defaultlimits(::Tuple{Any, Any}, ::Any, ::Any)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:1418
defaultlimits(::Tuple{Nothing, Nothing}, ::Any)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:1429
defaultlimits(::Nothing, ::Any)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:1424
...
Stacktrace:
[1] defaultlimits(userlimits::Tuple{Tuple{String, String}, Tuple{Float64, Float64}}, xscale::Function, yscale::Function)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:1419
[2] initialize_block!(ax::Axis; palette::Nothing)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:158
[3] initialize_block!(ax::Axis)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks/axis.jl:150
[4] _block(T::Type{…}, fig_or_scene::Figure, args::Vector{…}, kwdict::Dict{…}, bbox::Nothing; kwdict_complete::Bool)
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:371
[5] _block
@ ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:291 [inlined]
[6] #_block#1420
@ ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:259 [inlined]
[7] _block(::Type{Axis}, ::GridPosition; kwargs::@Kwargs{limits::Tuple{Tuple{…}, Tuple{…}}, aspect::DataAspect})
@ Makie ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:253
[8] _block
@ ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:246 [inlined]
[9] #_#1418
@ ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:237 [inlined]
[10] Block
@ ~/.julia/packages/Makie/qMluh/src/makielayout/blocks.jl:236 [inlined]
[11] plot(pyramid::Pyramid{…}; colorbar::Bool, kwargs::@Kwargs{})
@ PyramidScheme ~/Documents/PyramidScheme/src/PyramidScheme.jl:432
[12] top-level scope
@ REPL[64]:1
Some type information was truncated. Use `show(err)` to see complete types. |
This is because we don't handle additional dimensions not properly, but the rgb plotting does also not work. |
Could we also cache the Pyramid that we get from a provider? |
This will expose PyramidProvider which can then be served via HTTP so that it can be inserted into QGIS as an XYZTiles provider.
This kind of works now and I managed to setup a small html page which uses leaflet to show the pyramid provider, but this is quite laggy, because it throws the following error while zooming around the map: Error: handle_connection handler error.
│
│ ===========================
│ HTTP Error message:
│
│ ERROR: IOError: write: broken pipe (EPIPE)
│ Stacktrace:
│ [1] uv_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│ @ Base ./stream.jl:1091
│ [2] unsafe_write(s::Sockets.TCPSocket, p::Ptr{UInt8}, n::UInt64)
│ @ Base ./stream.jl:1145
│ [3] unsafe_write
│ @ ~/.julia/packages/HTTP/sJD5V/src/Connections.jl:132 [inlined]
│ [4] write
│ @ ./strings/io.jl:248 [inlined]
│ [5] write
│ @ ./io.jl:794 [inlined]
│ [6] unsafe_write(http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}, p::Ptr{UInt8}, n::UInt64)
│ @ HTTP.Streams ~/.julia/packages/HTTP/sJD5V/src/Streams.jl:95
│ [7] unsafe_write
│ @ ./io.jl:803 [inlined]
│ [8] write(s::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}, A::Vector{UInt8})
│ @ Base ./io.jl:837
│ [9] (::HTTP.Handlers.var"#1#2"{PyramidScheme.var"#56#57"{PyramidScheme.PyramidProvider{PyramidScheme.Pyramid{Int16, 2, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, DiskArrays.SubDiskArray{Int16, 2, Zarr.ZArray{Int16, 3, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64}, false}, YAXArrays.Cubes.YAXArray{Int16, 2, DiskArrays.SubDiskArray{Int16, 2, Zarr.ZArray{Int16, 3, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64}, false}, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, Dict{String, Any}}, Vector{YAXArrays.Cubes.YAXArray{Float64, 2, Zarr.ZArray{Float64, 2, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, Dict{String, Any}}}, Dict{Any, Any}}}}})(stream::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}})
│ @ HTTP.Handlers ~/.julia/packages/HTTP/sJD5V/src/Handlers.jl:61
│ [10] #invokelatest#2
│ @ ./essentials.jl:1055 [inlined]
│ [11] invokelatest
│ @ ./essentials.jl:1052 [inlined]
│ [12] handle_connection(f::Function, c::HTTP.Connections.Connection{Sockets.TCPSocket}, listener::HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, readtimeout::Int64, access_log::Nothing)
│ @ HTTP.Servers ~/.julia/packages/HTTP/sJD5V/src/Servers.jl:469
│ [13] (::HTTP.Servers.var"#16#17"{HTTP.Handlers.var"#1#2"{PyramidScheme.var"#56#57"{PyramidScheme.PyramidProvider{PyramidScheme.Pyramid{Int16, 2, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, DiskArrays.SubDiskArray{Int16, 2, Zarr.ZArray{Int16, 3, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64}, false}, YAXArrays.Cubes.YAXArray{Int16, 2, DiskArrays.SubDiskArray{Int16, 2, Zarr.ZArray{Int16, 3, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64}, false}, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, Dict{String, Any}}, Vector{YAXArrays.Cubes.YAXArray{Float64, 2, Zarr.ZArray{Float64, 2, Zarr.BloscCompressor, Zarr.ConsolidatedStore{Zarr.HTTPStore}}, Tuple{lon{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ForwardOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}, lat{DimensionalData.Dimensions.Lookups.Sampled{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, DimensionalData.Dimensions.Lookups.ReverseOrdered, DimensionalData.Dimensions.Lookups.Regular{Float64}, DimensionalData.Dimensions.Lookups.Points, DimensionalData.Dimensions.Lookups.NoMetadata}}}, Dict{String, Any}}}, Dict{Any, Any}}}}}, HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, Set{HTTP.Connections.Connection}, Int64, Nothing, ReentrantLock, Base.Semaphore, HTTP.Connections.Connection{Sockets.TCPSocket}})()
│ @ HTTP.Servers ~/.julia/packages/HTTP/sJD5V/src/Servers.jl:401
│ request =
│ HTTP.Messages.Request:
│ """
│ GET /8/86/131.png HTTP/1.1
│ Host: 127.0.0.1:8765
│ User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0
│ Accept: image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
│ Accept-Language: de,en;q=0.7,en-US;q=0.3
│ Accept-Encoding: gzip, deflate, br, zstd
│ DNT: 1
│ Connection: keep-alive
│ Referer: http://127.0.0.1:3000/
│ Sec-Fetch-Dest: image
│ Sec-Fetch-Mode: no-cors
│ Sec-Fetch-Site: same-site
│ Priority: u=4, i
│
│ """
└ @ HTTP.Servers ~/.julia/packages/HTTP/sJD5V/src/Servers.jl:483 |
ToDos: |
This adds abstraction layers to treat any Pyramid as a TileProvider and also adds a
Pyramid
constructor to lazily expose a TileProvider as a Pyramid.